package cnm.red5;

import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.service.IServiceCapableConnection;
import org.red5.server.api.IScope;

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.UUID;
import java.lang.Integer;

import cnm.storage.StorageService;
import cnm.model.*;
import cnm.dao.*;

public class Application extends MultiThreadedApplicationAdapter {

	private ColumnDAO columnDAO;
	private ProgramDAO programDAO;
	private UserDAO userDAO;
	private BoardDAO boardDAO;
	private StorageService storageService;
	
	public void setColumnDAO(ColumnDAO columnDAO)
	{
		this.columnDAO = columnDAO;
	}
	
	public void setProgramDAO(ProgramDAO programDAO)
	{
		this.programDAO = programDAO;
	}
	
	public void setUserDAO(UserDAO userDAO)
	{
		this.userDAO = userDAO;
	}

	public void setBoardDAO(BoardDAO boardDAO)
	{
		this.boardDAO = boardDAO;
	}
	
	public void setStorageService(StorageService storageService) {
		this.storageService = storageService;
	}
	
	@Override
	public boolean appStart(IScope app) {
		//codecService.addListener(this);
		return super.appStart(app);
	}

	@Override
	public void appStop(IScope app) {
		//codecService.removeListener(this);
		super.appStop(app);
	}

	/**
	 * Return the columnList.
	 * 
	 * @param params
	 * 			map including keys: "index", "length"
	 * @return 0 - column exist, 304 - column not exist
	 * 			result ColumnList	
	 * @throws ServiceException
	 */
	public Result getAllColumns(IConnection con, Map<String, Object> params) throws Exception
	{
		try {
			List<Column> list = columnDAO.findAll(
					Integer.parseInt(params.get("index").toString()),
					Integer.parseInt(params.get("length").toString()), 
					null
					);
			return new Result(list.toArray());
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}
	
	public Result getColumnCount(IConnection con, Map<String, Object> params) throws Exception
	{
		try {
			Long count = columnDAO.getCount();
			return new Result(count);
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}
	
	public Result updateColumn(IConnection con, Map<String, Object> params) throws Exception
	{
		try {
			int columnId = Integer.parseInt((String) params.get("id"));
			String columnDesc = (String) params.get("desc");			
			Column column = (Column) columnDAO.findById(columnId);
			column.setColumnDesc(columnDesc);
			columnDAO.update(column);
			return new Result(ErrorType.NO_ERROR);
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}
	
	public Result getColumnByUuid(IConnection con, Map<String, Object> params) throws Exception
	{
		String columnUuid = (String) params.get("uuid");
		Column column;
		try {
			column = columnDAO.findByUuid(columnUuid);
			return new Result(column);
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}	
	
	@SuppressWarnings("unchecked")
	public Result searchProgram(IConnection con, Map<String, Object> params) throws Exception
	{
		try {
			String keyword = (String) params.get("keyword");
			String columnUuid = (String) params.get("columnUuid");
			int index = Integer.parseInt(params.get("index").toString());
			int length = Integer.parseInt(params.get("length").toString());
			List<Program> list;
			if (columnUuid != null && !columnUuid.equals("")) {
				list = programDAO.findByColumn(columnUuid, index, length);
			} else if (keyword.equals("")) {
				Sorter sorter = Sorter.desc("programDate");
				list = programDAO.findAll(index, length, sorter);
			} else {
				list = programDAO.findByKeyword(keyword, index, length);
			}

			ArrayList piList = new ArrayList();
			for (int i = 0; i<list.size(); i++) {
				ProgramInfo pi = new ProgramInfo();
				//int columnId = list.get(i).getColumn().getColumnId();
				pi.setColumnId(list.get(i).getColumn().getColumnId());
				pi.setColumnName(list.get(i).getColumn().getColumnName());
				pi.setProgramName(list.get(i).getProgramName());
				pi.setProgramDate(list.get(i).getProgramDate());
				pi.setProgramDesc(list.get(i).getProgramDesc());
				pi.setProgramDj(list.get(i).getProgramDj());
				pi.setProgramId(list.get(i).getProgramId());
				pi.setProgramUuid(list.get(i).getProgramUuid());
				piList.add(pi);
			}
			return new Result(piList.toArray());
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}
		
	public Result getProgramCount(IConnection con, Map<String, Object> params) throws Exception
	{
		try {
			String keyword = (String) params.get("keyword");
			String columnUuid = (String) params.get("columnUuid");
			Long count;
			if (columnUuid != null && !columnUuid.equals("")) {
				count = programDAO.getCountByColumn(columnUuid);
			} else if (keyword.equals("")) {
				count = programDAO.getCount();
			} else {
				count = programDAO.getCountByKeyword(keyword);
			}
			return new Result(count);
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}
	
	public Result saveProgram(IConnection con, Map<String, Object> params) throws Exception 
	{
		try {
			String uuid = (String) params.get("uuid");			
    		String programDate = (String) params.get("programDate");
       		String programDesc = (String) params.get("programDesc");
       		String programDj = (String) params.get("programDj");
       		String programName = (String) params.get("programName");
       		String columnUuid = (String) params.get("columnUuid");
       		Column column = columnDAO.findByUuid(columnUuid);
       		
			Program program = new Program();
    		program.setProgramDate(programDate);
    		program.setProgramDesc(programDesc);
    		program.setProgramDj(programDj);
    		program.setProgramName(programName);
    		program.setProgramUuid(uuid);
    		program.setColumn(column);
    		int programId = programDAO.save(program);
			return new Result(new Integer(programId));			
		} catch(Exception e) {
			e.printStackTrace();
		} 	
		return new Result(ErrorType.SYSTEM_ERROR);
	}
	
	public Result deleteProgram(IConnection con, Map<String, Object> params) throws Exception 
	{
		try {
			int id = Integer.parseInt(params.get("id").toString());
			Program program = programDAO.findById(id);
			storageService.deleteResourceObject(
					ResourceTypes.TYPE_AUDIO, 
					program.getProgramUuid()
					);
			programDAO.delete(program);
			return new Result(ErrorType.NO_ERROR);			
		} catch(Exception e) {
			e.printStackTrace();
		} 	
		return new Result(ErrorType.SYSTEM_ERROR);
	}
		
	@SuppressWarnings("unchecked")
	public Result searchBoard(IConnection con, Map<String, Object> params) throws Exception
	{
		try {
			String keyword = (String) params.get("keyword");
			int index = Integer.parseInt(params.get("index").toString());
			int length = Integer.parseInt(params.get("length").toString());
			List<Board> list;
			if (keyword.equals("")) {
				Sorter sorter = Sorter.desc("boardId");
				list = boardDAO.findAll(index, length, sorter);
			} else {
				list = boardDAO.findByKeyword(keyword, index, length);
			}
			return new Result(list.toArray());
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}
		
	public Result getBoardCount(IConnection con, Map<String, Object> params) throws Exception
	{
		try {
			String keyword = (String) params.get("keyword");
			Long count;
			if (keyword.equals("")) {
				count = boardDAO.getCount();
			} else {
				count = boardDAO.getCountByKeyword(keyword);
			}
			return new Result(count);
		}
		catch (Exception e)
		{			
			e.printStackTrace();
		}		
		return new Result(ErrorType.SYSTEM_ERROR);
	}

	public Result saveBoard(IConnection con, Map<String, Object> params) throws Exception 
	{
		try {
			String uuid = (String) params.get("uuid");			
    		String boardDate = (String) params.get("boardDate");
       		String boardDesc = (String) params.get("boardDesc");
       		int boardType = Integer.parseInt(params.get("boardType").toString());
       		String boardName = (String) params.get("boardName");

       		Board board = new Board();
       		board.setBoardDate(boardDate);
       		board.setBoardDesc(boardDesc);
       		board.setBoardName(boardName);
       		board.setBoardType(boardType);
       		board.setBoardUuid(uuid);
       		
    		int boardId = boardDAO.save(board);
			return new Result(new Integer(boardId));			
		} catch(Exception e) {
			e.printStackTrace();
		} 	
		return new Result(ErrorType.SYSTEM_ERROR);
	}	
	
	public Result deleteBoard(IConnection con, Map<String, Object> params) throws Exception 
	{
		try {
			int id = Integer.parseInt(params.get("id").toString());
			Board board = boardDAO.findById(id);
			if (board.getBoardType() == BoardTypes.TYPE_PROGRAM_LIST) {
    			storageService.deleteResourceObject(
    					ResourceTypes.TYPE_IMAGE, 
    					board.getBoardUuid()
    					);
			}
			boardDAO.delete(board);
			return new Result(ErrorType.NO_ERROR);			
		} catch(Exception e) {
			e.printStackTrace();
		} 	
		return new Result(ErrorType.SYSTEM_ERROR);
	}
	
	public Result getLatestBoard(IConnection con, Map<String, Object> params) throws Exception 
	{
		try {
			int type = Integer.parseInt(params.get("type").toString());
			if (type != BoardTypes.TYPE_PROGRAM_LIST && 
					type != BoardTypes.TYPE_ACTIVITY_NOTICE) {
				return new Result(ErrorType.SYSTEM_ERROR);
			}
			Board board = boardDAO.getLatestBoard(type);
			if (type == BoardTypes.TYPE_PROGRAM_LIST) {
				return new Result(board.getBoardUuid());
			} else {
				return new Result(board.getBoardDesc());
			}
		} catch(Exception e) {
			e.printStackTrace();
		} 	
		return new Result(ErrorType.SYSTEM_ERROR);
	}
	
}
